package nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public class NioServer {

    private static Map<String,SelectionKey> clientSelectionKeys = new HashMap();

    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);//非阻塞
        serverSocketChannel.socket().bind(new InetSocketAddress(8899));

        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true){
            selector.select();
            Set<SelectionKey> selectionKeySet = selector.selectedKeys();
            selectionKeySet.forEach(selectionKey -> {
                final SocketChannel client;
                if(selectionKey.isAcceptable()){
                    try{
                        ServerSocketChannel server = (ServerSocketChannel)selectionKey.channel();
                        client = server.accept();
                        client.configureBlocking(false);
                        SelectionKey clientKey = client.register(selector,SelectionKey.OP_READ);
                        clientSelectionKeys.put("【" + UUID.randomUUID().toString() + "】",clientKey);
                    }catch (IOException ex){
                        ex.printStackTrace();
                    }
                }else if(selectionKey.isReadable()){
                    try{
                        client = (SocketChannel)selectionKey.channel();
                        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                        int count = client.read(readBuffer);
                        if(count > 0){
                            readBuffer.flip();
                            Charset charset = Charset.forName("utf-8");
                            String receivedMessage = String.valueOf(charset.decode(readBuffer).array());
                            System.out.println(client + ": " + receivedMessage);

                            String clientSelectionKey = null;

                            for (Map.Entry<String,SelectionKey> entry : clientSelectionKeys.entrySet()){
                                if(selectionKey == entry.getValue()){
                                    clientSelectionKey = entry.getKey();
                                    break;
                                }
                            }

                            for (Map.Entry<String,SelectionKey> entry : clientSelectionKeys.entrySet()){
                                SocketChannel clientSocketChannel = (SocketChannel) entry.getValue().channel();
                                ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
                                writeBuffer.put((clientSelectionKey + ": " + receivedMessage).getBytes());

                                writeBuffer.flip();

                                clientSocketChannel.write(writeBuffer);
                            }

                        }
                    }catch (IOException ex){
                        ex.printStackTrace();
                    }
                }
            });
            selectionKeySet.clear();
        }
    }
}
